﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using QuickGraph.Algorithms.ShortestPath;
using QuickGraph.Algorithms.Observers;
using QuickGraph.Algorithms;

namespace VirtualOperator
{
   public class RoutingController
    {
     


        public RoutingController()
        {
            
        }

        private class SetupStore
        {
            public int source { get; set; }
            public int target { get; set; }
            public VirtualNetwork ownTopology { get; set; }
            public List<VirtualNetwork.Link> path { get; set; }
            
            public int connectN { get; set; }
            public int requieredCapacity { get; set; }
            public SetupStore(int source, int target, VirtualNetwork ownTopology, int requieredCapacity)
            {
                this.source = source;
                this.target = target;
                this.ownTopology = ownTopology;
                path = new List<VirtualNetwork.Link>();
              
                this.requieredCapacity = requieredCapacity;

            }
        }



        public static List<VirtualNetwork.Link> setupConnection(VirtualNetwork topology, int src, int trg, int requieredCapacity)
        {
            VirtualNetwork ownTopology = topology.Clone();
            SetupStore ss = new SetupStore(src, trg, ownTopology, requieredCapacity);
            if (ss.ownTopology.EdgeCount != 0)
            {
                if (findBestPath(ss))  
                {
                    return ss.path;
                }
                return null;
            }
            return null;
        }


        private static VirtualNetwork.Matrix IDtoNode(int id, VirtualNetwork ownTopology)
        {

            return ownTopology.Vertices.ToList().Find(delegate(VirtualNetwork.Matrix no)
            {
                return no.ID == id;
            });

        }




        private static Boolean findBestPath(SetupStore ss)
        {
            //  Func<Topology.Link, double> edgeCost = e => 1; //koszty lini takie same
            Dictionary<VirtualNetwork.Link, double> edgeCost = new Dictionary<VirtualNetwork.Link, double>(ss.ownTopology.EdgeCount);

            int index = 0;
            int max = ss.ownTopology.EdgeCount;
            while (index < max)
            {       //free capisity < requierd
                if (ss.ownTopology.Edges.ElementAt(index).Capacity < ss.requieredCapacity )
                {
                    ss.ownTopology.RemoveEdge(ss.ownTopology.Edges.ElementAt(index));
                    max = ss.ownTopology.EdgeCount;
                }
                else
                    index++;
            }
            foreach (var e in ss.ownTopology.Edges)
            {
                edgeCost.Add(e, e.Capacity);
            }

            // We want to use Dijkstra on this graph
            var dijkstra = new DijkstraShortestPathAlgorithm<VirtualNetwork.Matrix, VirtualNetwork.Link>(ss.ownTopology, e => edgeCost[e]);

            // Attach a Vertex Predecessor Recorder Observer to give us the paths
            var predecessorObserver = new VertexPredecessorRecorderObserver<VirtualNetwork.Matrix, VirtualNetwork.Link>();
            predecessorObserver.Attach(dijkstra);
            dijkstra.Compute(IDtoNode(ss.source, ss.ownTopology));
            IEnumerable<VirtualNetwork.Link> path;
            //List<Topology.Link> ddd = new List<Topology.Link>();
            if (predecessorObserver.TryGetPath(IDtoNode(ss.target, ss.ownTopology), out path))
            {
                ss.path.AddRange(path);
                return true;
            }
            else return false;
        }

    }
}
